アクションの基本 – Ember.js入門(4)
1.0.0がリリースされたのにも関わらず、あまり盛り上がっていないEmber.jsですが、めげずに入門シリーズを継続します。
Ember.jsは、日本語の情報が致命的に少ないというのもありますが、@emadurandal 氏が翻訳した公式ドキュメントが公開されています。本稿執筆時点では全ドキュメントの翻訳が完了しているわけではありませんが、学習の大きな手助けになると思います。また、同じ札幌で活躍されている@tricknotes氏による「はじめるEmber.js!!」Ember.js入門セッションの資料がSlideshareにあります。こちらもEmber.jsをはじめる時には役立つ資料となると思いますので、本ブログの入門シリーズと合わせてチェックしてみてください。
なお、今の所、Ember.jsが、これからどのようになっていくかは解りません。もしかしたら、メジャーなフレームワークとして成長していくかもしれませんし、あっという間に闇に呑まれてしまうかもしれません。とはいえ、新しい技術をやるには、そういったリスクはつきものです。しかし、クライアントサイドのJavaScriptベースのMVCフレームワークは、どれかひとつは習得しておくべき技術分野だと思います。このため、このシリーズでは、MVCの概念や基本的なパターンなども学べるように、丁寧に書いていく予定です。
それでは、今回はEmber.jsのアクションについて解説します。
イベントとイベント駆動
ユーザインターフェイスは、ユーザとシステムとの間にあるシステム境界です。ユーザは、ユーザインターフェイスを介してシステムを操作します。それは、ボタンやリンクなどです。このような操作は、プログラム内ではイベントとして処理されます。一般的に、イベントをトリガーとして処理を行うプログラムは、イベント駆動(Event Driven)と呼びます。また、イベントを処理する関数やオブジェクトをイベントハンドラーと呼びます。
イベント処理の定義
クライアントサイドで、イベント駆動のアプリケーションを作成するには、ボタンなどに対してJavaScriptの関数として定義したイベントハンドラーを関連付けることを行います。はじめに、Ember.jsを利用しない場合の書き方をおさらいしておきましょう。
HTMLのタグに定義する
イベント処理を定義する最も原始的な方法は、onclickイベントなどをHTMLのタグに定義することです。例えば、次のコードではボタンをクリックした時にコンソールログを表示します。
<button onclick="javascript:console.debug('clicked!')">Click Me!</button>
この定義方法は非常に直感的ですが、多くのイベントを定義していくと直ぐに見通しが悪くなってしまいます。これは、HTML(View)にイベントハンドラーを定義してしまっていることが原因です。
jQueryを使ったイベント処理の定義
jQueryなどのライブラリを使えば、簡単にイベントハンドラーをViewから独立して定義できます。そうすることで、イベントを同じ階層で見られるようになり、可読性が良くなります。
次のコードは、先ほどと同じイベント処理をjQueryを使って記述したコードです。
<button id="button">Click Me!</button>
$(function() { $('#button').on('click', function() { console.debug('clicked!'); }); });
jQueryについての詳細な解説は省略しますが、HTML(View)では各コンポーネントを識別するためにidを付与しています。そして、スクリプトでそのコンポーネントに対して、イベントハンドラーとなる関数を結びつけています。
このように、jQueryなどを使うことで、イベントハンドラーをViewから独立させることはできます。しかし、あくまでも、コンポーネントとイベントハンドラーを結びつける手続き的なコードです。それでも十分な場合も多いですが、クライアントサイドをMVCのアプリケーションとして実装するには物足りません。ここがMVCアプリケーションフレームワークとjQuery単体の大きな違いのひとつとなります。
Ember.jsのAction
Ember.jsを使えば、各画面(View)に対応するControllerに、自然な形でイベントハンドラーを定義することができます。
ControllerにActionを定義する
先に、JavaScriptのコードをみていきます。
window.App = Ember.Application.create(); App.ApplicationController = Ember.ObjectController.extend({ actions: { foo: function() { console.debug('clicked!'); } } });
2行目でControllerを明示的に定義しています。この時、Ember.ObjectControllerクラスを基底クラスとなるように、継承します。Ember.jsではクラスの継承をextendメソッドを使って行う作法になっているので覚えておきましょう。
extends関数はハッシュを引数として持ち、ここに継承元クラスを拡張する定義を記述します。ここでは、アクションはactionsとして「アクション名」をキーに、対応する関数をバリューとして定義するだけの直感的で宣言的な記述です。
なお、Ember.jsではControllerの定義を省略した場合、対応するModelなどから適合するデフォルトのControllerが作成されます。しかし、あまり命名規約に頼って省略しても嵌まったときに大変なので、自分は明示的に定義した方が良いと思います。
ViewにActionを設定する
View(テンプレート)では、Controllerに定義したactionを{{action}}ヘルパーを使って定義します。
<p><button {{action 'foo'}}>Click Me!</button></p>
このように、{{action}}ヘルパーにはControllerのactionsに定義したアクション名を指定してください。なお、追加でパラメータを指定し、action関数に渡すことも可能です。
Ember.jsではこれだけの記述で、コンポーネントとイベントハンドラを関連付けることができます。
まとめ
Ember.jsでは、必要最低限の記述でViewから発生したイベントを処理する関数を宣言的に定義することができます。なお、流れ的には、バインディング - Ember.js入門(5)に繋がってますので、続けてご覧ください。
最後にコード全体を掲載します。
<!doctype html> <html> <head> <meta charset="utf-8"> <title>Actionの基本 - Ember.js</title> </head> <body> <script type="text/x-handlebars"> <h1>HTML event</h1> <button onclick="javascript:console.debug('clicked!');">Click Me!</button> <h1>jQuery</h1> <button id="button">Click Me!</button> <h1>Actions</h1> <p><button {{action 'foo'}}>Click Me!</button></p> </script> <script type="text/javascript" src="js/libs/jquery-1.9.1.js"></script> <script type="text/javascript" src="js/libs/handlebars-1.0.0.js"></script> <script type="text/javascript" src="js/libs/ember-1.0.0.js"></script> <script type="text/javascript"> window.App = Ember.Application.create(); App.ApplicationController = Ember.ObjectController.extend({ actions: { foo: function() { console.debug('clicked!'); } } }); $(function() { $('#button').on('click', function() { console.debug('clicked!'); }); }); </script> </body> </html>